package com.ex.net;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.ex.util.LogUtil;
import com.example.androiddemo.Const;

/**
 * java.net.Socket 的通信方式， 阻塞式接收，不阻塞式发送
 * 
 * 完整会话：锁住，等待回复或超时解锁
 * 
 * 消息发送、接收处理 等在子线程中处理
 * 
 * @author thduan
 * 2015-9-17 14:30:44
 */
public class SocketDemo {
	
	private Socket socket;
	private PrintWriter pw;
	private BufferedReader br;
	
	private SocketListener socketListener;
	
	/** 线程池 ， 验证： 连续发消息，如果一个线程，那么execute 时要等待 ，两个线程，那么可以并行 */
	private ExecutorService service;
	
	/** socket 线程： 连接、数据接收监控 */
	private Thread socketThread;
	
	public SocketDemo() {
		service = Executors.newFixedThreadPool(5);
		socketThread = new Thread(new SocketRunnable());
		socketThread.start();
	}
	
	public class SocketRunnable implements Runnable{

		@Override
		public void run() {
			try {
				socket = new Socket(Const.SOCKET_ADDRESS, Const.SOCKET_PORT);
				pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")));
				br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
				String line = "";
				while ((line=br.readLine()) != null) {
					receive(line);
				}
				
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	/**
	 * 消息接收监听设置
	 * @param listener
	 */
	public void setListener(SocketListener listener) {
		this.socketListener = listener;
	}
	
	private int receiveCnt = 0;
	/**
	 * 接收到消息
	 * @param msg
	 */
	private void receive(String msg) {
		String recMsg = "server 消息" + (++receiveCnt) + " : " +  msg;
		LogUtil.log(recMsg + ", time: " + System.currentTimeMillis());
		
		Message message = Message.obtain(uiHandler, 0);
		message.obj = recMsg;
		
		message.sendToTarget();
	}
	
	/**
	 * 发送消息，并接收回复，代表发送是否成功
	 * @param msg
	 */
	public void sendMsgReq(final String msg, final SocketResLis lis) {
		service.execute(new Runnable() {
			
			@Override
			public void run() {
				pw.println(msg);
				pw.flush();
			}
		});
	}
	
	private static final String RECEIVE_MSG_KEY = "receiveMsgKey";
	/**
	 * 与UI线程交互
	 */
	private Handler uiHandler = new Handler(Looper.getMainLooper()) {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				if(socketListener != null) {
					String recMsg = (String) msg.obj;
					
					if(null != recMsg && socketListener != null) {
						socketListener.onReceive(recMsg);
					}
				}
				break;

			default:
				break;
			}
		};
	};
	
	/**
	 * 关闭socket
	 * 有问题： 会向服务发无限个 空消息
	 */
	public void closeServer() {
		if(pw != null) {
			pw.close();
		}
		if(br != null) {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(socketThread != null) {
			try {
				socketThread.join(1 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		service.shutdown();
		
		if(socket != null) {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
